//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - SaaS Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Data;

using Microsoft.Practices.EnterpriseLibrary.Data;

using Shp.Runtime.Services.Properties;
using Shp.Runtime.Contract;

namespace Shp.Runtime.Services
{
    static public class PresentationLogic
    {
        static public int GetConfiguredLayout(string tenantAlias)
        {
            int layout;
            Database db = DatabaseFactory.CreateDatabase(Constants.DB.TenantMetadataStore);
            using (DbCommand command = db.GetStoredProcCommand("dbo.GetConfiguredLayout"))
            {
                db.AddInParameter(command, "tenantAlias", DbType.String, tenantAlias);
                layout = (int)db.ExecuteScalar(command);
            }
            return layout;
        }

        static public Guid GetCurrentStyleId(Guid tenantId)
        {
            Guid currentId = Guid.Empty;

            Database db = DatabaseFactory.CreateDatabase(Constants.DB.TenantMetadataStore);
            using (DbCommand command = db.GetStoredProcCommand("dbo.GetCurrentStyleId"))
            {
                db.AddInParameter(command, "tenantId", DbType.Guid, tenantId);
                currentId = new Guid(db.ExecuteScalar(command).ToString());
            }

            return currentId;
        }

        static public string GetConfiguredStyle(string tenantAlias)
        {
            string style;
            Database db = DatabaseFactory.CreateDatabase(Constants.DB.TenantMetadataStore);
            using (DbCommand command = db.GetStoredProcCommand("dbo.GetConfiguredStyle"))
            {
                db.AddInParameter(command, "tenantAlias", DbType.String, tenantAlias);
                style = (string)db.ExecuteScalar(command);
            }
            return style;
        }

        static public StringPair[] GetMainMenu(string tenantAlias, bool isPublic)
        {
            Database db = DatabaseFactory.CreateDatabase(Constants.DB.TenantMetadataStore);
            List<StringPair> list = new List<StringPair>();
            // we add the options dynamically
            using (DbCommand command = db.GetStoredProcCommand("dbo.GetMainMenu"))
            {
                db.AddInParameter(command, "tenantAlias", DbType.String, tenantAlias);
                db.AddInParameter(command, "isPublic", DbType.Boolean, isPublic);
                using (IDataReader reader = db.ExecuteReader(command))
                {
                    while (reader.Read())
                    {
                        StringPair pair = new StringPair();
                        pair.Key = reader.GetString(0);
                        pair.Value = reader.GetString(1);
                        if (StringPair.ContainsKey(pair.Key, list))
                        {
                            // An incosistent view definition has been added directly to the db
                            // you should guard against this behaviour
                            throw new System.Security.SecurityException(Resources.InvalidConfigurationDuplicateKey);
                        }
                        else
                        {
                            list.Add(pair);
                        }
                    }
                }
            }
            return list.ToArray();
        }

        static public KeyValuePair<int, string>[] GetLayoutList(Guid tenantId)
        {
            List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>();
            list.Add(new KeyValuePair<int, string>(0, "classic"));
            list.Add(new KeyValuePair<int, string>(1, "functional"));
            return list.ToArray();
        }

        static public KeyValuePair<Guid, string>[] GetStyleList(Guid tenantId)
        {
            Database db = DatabaseFactory.CreateDatabase(Constants.DB.TenantMetadataStore);
            List<KeyValuePair<Guid, string>> list = new List<KeyValuePair<Guid, string>>();
            using (DbCommand command = db.GetStoredProcCommand("dbo.GetStyleList"))
            {
                db.AddInParameter(command, "tenantId", DbType.Guid, tenantId);
                using (IDataReader reader = db.ExecuteReader(command))
                {
                    while (reader.Read())
                    {
                        Guid key = reader.GetGuid(0);
                        string value = reader.GetString(1);
                        list.Add(new KeyValuePair<Guid, string>(key, value));
                    }
                }
            }
            return list.ToArray();
        }

        static public void UpdatePresentation(Guid tenantId, int layout, Guid style)
        {
            Database db = DatabaseFactory.CreateDatabase(Constants.DB.TenantMetadataStore);
            using (DbCommand command = db.GetStoredProcCommand("dbo.UpdatePresentation"))
            {
                db.AddInParameter(command, "tenantId", DbType.Guid, tenantId);
                db.AddInParameter(command, "layout", DbType.Int32, layout);
                db.AddInParameter(command, "style", DbType.Guid, style);
                db.ExecuteNonQuery(command);
            }
        }

        static public void AddStyle(Guid tenantId, string name, Uri url)
        {
            Database db = DatabaseFactory.CreateDatabase(Constants.DB.TenantMetadataStore);
            using (DbCommand command = db.GetStoredProcCommand("dbo.AddStyle"))
            {
                db.AddInParameter(command, "tenantId", DbType.Guid, tenantId);
                db.AddInParameter(command, "name", DbType.String, name);
                db.AddInParameter(command, "url", DbType.String, url.AbsoluteUri);
                db.ExecuteNonQuery(command);
            }
        }

        static public MainMenuItem[] GetMainMenuList(Guid tenantId)
        {
            Database db = DatabaseFactory.CreateDatabase(Constants.DB.TenantMetadataStore);
            List<MainMenuItem> list = new List<MainMenuItem>();
            using (DbCommand command = db.GetStoredProcCommand("dbo.GetMainMenuList"))
            {
                db.AddInParameter(command, "tenantId", DbType.Guid, tenantId);
                using (IDataReader reader = db.ExecuteReader(command))
                {
                    while (reader.Read())
                    {
                        MainMenuItem item = new MainMenuItem();
                        item.Description = reader["description"].ToString();
                        item.Url = reader["url"].ToString();
                        item.IsPublic = (bool)reader["isPublic"];
                        list.Add(item);
                    }
                }
            }
            return list.ToArray();
        }

        static public void UpdateMainMenu(Guid tenantId, MainMenuItem[] menuItems)
        {
            Dictionary<string, MainMenuItem> list = new Dictionary<string, MainMenuItem>();

            foreach (MainMenuItem item in menuItems)
            {
                string key = item.Description + item.IsPublic.ToString();

                if (list.ContainsKey(key))
                {
                    throw new System.Security.SecurityException(Resources.InvalidConfigurationDuplicateKey);
                }
                else
                {
                    list.Add(key, item);
                }
            }

            Database db = DatabaseFactory.CreateDatabase(Constants.DB.TenantMetadataStore);

            using (DbConnection conn = db.CreateConnection())
            {
                conn.Open();

                string deleteCmdSql = "DELETE dbo.[MainMenu] WHERE tenantId = @tenantId";
                using (DbCommand deleteCmd = db.GetSqlStringCommand(deleteCmdSql))
                {
                    db.AddInParameter(deleteCmd, "@tenantId", DbType.Guid, tenantId);
                    deleteCmd.Connection = conn;
                    deleteCmd.ExecuteNonQuery();
                }

                string insertCmdSql = "INSERT INTO dbo.[MainMenu] (id, tenantId, description, url, isPublic, ordinal)" +
                                      " VALUES (@ID, @TenantID, @Description, @Url, @IsPublic, @Ordinal)";
                int ordinal = 1;

                foreach (MainMenuItem item in list.Values)
                {
                    DbCommand insertCmd = db.GetSqlStringCommand(insertCmdSql);

                    db.AddInParameter(insertCmd, "@ID", DbType.Guid, Guid.NewGuid());
                    db.AddInParameter(insertCmd, "@TenantID", DbType.Guid, tenantId);
                    db.AddInParameter(insertCmd, "@Description", DbType.String, item.Description);
                    db.AddInParameter(insertCmd, "@Url", DbType.String, item.Url);
                    db.AddInParameter(insertCmd, "@IsPublic", DbType.Boolean, item.IsPublic);
                    db.AddInParameter(insertCmd, "@Ordinal", DbType.Int32, ordinal);

                    ordinal++;

                    insertCmd.Connection = conn;
                    insertCmd.ExecuteNonQuery();
                }
            }
        }
    }
}
